<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Funqy Knative Events Binding</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/funqy-knative-events" />
  <meta property="og:title" content="Quarkus - Funqy Knative Events Binding" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/funqy-knative-events">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Funqy Knative Events Binding</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#setting-up-knative">Setting up Knative</a></li>
<li><a href="#read-about-cloud-events">Read about Cloud Events</a></li>
<li><a href="#the-quickstart">The Quickstart</a></li>
<li><a href="#the-quickstart-flow">The Quickstart Flow</a></li>
<li><a href="#funqy-and-cloud-events">Funqy and Cloud Events</a></li>
<li><a href="#the-code">The Code</a></li>
<li><a href="#maven">Maven</a></li>
<li><a href="#dev-mode-and-testing">Dev mode and Testing</a></li>
<li><a href="#build-the-project">Build the Project</a></li>
<li><a href="#deploy-to-kubernetesopenshift">Deploy to Kubernetes/Openshift</a></li>
<li><a href="#run-the-demo">Run the demo</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus Funqy <a href="https://knative.dev/docs/eventing">Knative Events</a> builds off of the <a href="funqy-http">Funqy HTTP</a> extension to allow you to
route and process Knative Events within a Funqy function.</p>
</div>
<div class="paragraph">
<p>The guide walks through quickstart code to show you how you can deploy and invoke on Funqy functions
with Knative Events.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>60+ minutes</p>
</li>
<li>
<p>Read about <a href="funqy">Funqy Basics</a>.  This is a short read!</p>
</li>
<li>
<p>JDK 1.8+ installed with <code>JAVA_HOME</code> configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
<li>
<p>Have gone through the <a href="https://redhat-developer-demos.github.io/knative-tutorial/knative-tutorial/index.html">Knative Tutorial</a>, specifically <a href="https://redhat-developer-demos.github.io/knative-tutorial/knative-tutorial-eventing/eventing-trigger-broker.html">Brokers and Triggers</a></p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="setting-up-knative"><a class="anchor" href="#setting-up-knative"></a>Setting up Knative</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Setting up Knative locally in a Minikube environment is beyond the scope of this guide.  It is advised
to follow  <a href="https://redhat-developer-demos.github.io/knative-tutorial/knative-tutorial/index.html">this</a> Knative Tutorial
put together by Red Hat.  It walks through how to set up Knative on Minikube or Openshift in a local environment.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Specifically you should run the <a href="https://redhat-developer-demos.github.io/knative-tutorial/knative-tutorial-eventing/eventing-trigger-broker.html">Brokers and Triggers</a>
tutorial as this guide requires that you can invoke on a Broker to trigger the quickstart code.
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="read-about-cloud-events"><a class="anchor" href="#read-about-cloud-events"></a>Read about Cloud Events</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The Cloud Event <a href="https://cloudevents.io/">specification</a> is a good read to give you an even greater understanding of Knative Events.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-quickstart"><a class="anchor" href="#the-quickstart"></a>The Quickstart</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>funqy-knative-events-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-quickstart-flow"><a class="anchor" href="#the-quickstart-flow"></a>The Quickstart Flow</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The quickstart works by manually sending an HTTP request containing a Cloud Event to the Knative Broker using <code>curl</code>.
The Knative Broker receives the request and triggers the startup of the Funqy container built by the quickstart.
The event triggers the invocation of a chain of Funqy functions.  The output of one function triggers the
invocation of another Funqy function.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="funqy-and-cloud-events"><a class="anchor" href="#funqy-and-cloud-events"></a>Funqy and Cloud Events</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When living within a Knative Events environment, Funqy functions are triggered by a specific
Cloud Event type.  You can have multiple Funqy functions within a single application/deployment,
but they must be triggered by a specific Cloud Event Type.  The exception to this rule is if there is
only one Funqy function in the application.  In that case, the event is pushed to that function irregardless
of the Cloud Event type.</p>
</div>
<div class="paragraph">
<p>Currently, Funqy can only consume JSON-based data.  It supports both Binary and Structured mode of execution,
but the data component of the Cloud Event message must be JSON.  This JSON must also be marshallable to and from the
Java parameters and return types of your functions.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="the-code"><a class="anchor" href="#the-code"></a>The Code</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let&#8217;s start looking at our quickstart code so that you can understand how Knative Events map to Funqy.
Open up <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/src/main/java/org/acme/funqy/SimpleFunctionChain.java">SimpleFunctionChain.java</a></p>
</div>
<div class="paragraph">
<p>The first function we&#8217;ll look at is <code>defaultChain</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.funqy.Funq;

public class SimpleFunctionChain {
    @Funq
    public String defaultChain(String input) {
        log.info("*** defaultChain ***");
        return input + "::" + "defaultChain";
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>As is, a Funqy function has a default Cloud Event mapping.  By default, the Cloud Event type must match
the function name for the function to trigger.  If the function returns output,
the response is converted into a Cloud Event and returned to the Broker to be routed to other triggers.
The default Cloud Event type for this response is the function name + <code>.output</code>.  The default Cloud Event source is the function name.</p>
</div>
<div class="paragraph">
<p>So, for the <code>defaultChain</code> function, the Cloud Event type that triggers the function is <code>defaultChain</code>.  It generates
a response that triggers a new Cloud Event whose type is <code>defaultChain.output</code> and the event source is <code>defaultChain</code>.</p>
</div>
<div class="paragraph">
<p>While the default mapping is simple, it might not always be feasible.  You can change this default mapping
through configuration.  Let&#8217;s look at the next function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.funqy.Funq;

public class SimpleFunctionChain {
    @Funq
    public String configChain(String input) {
        log.info("*** configChain ***");
        return input + "::" + "configChain";
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>configChain</code> function has its Cloud Event mapping changed by configuration within <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/src/main/resources/application.properties">application.properties</a>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">quarkus.funqy.knative-events.mapping.configChain.trigger=defaultChain.output
quarkus.funqy.knative-events.mapping.configChain.response-type=annotated
quarkus.funqy.knative-events.mapping.configChain.response-source=configChain</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this case, the configuration maps the incoming Cloud Event type <code>defaultChain.output</code> to the <code>configChain</code> function.
The <code>configChain</code> function maps its response to the <code>annotated</code> Cloud Event type, and the Cloud Event source <code>configChain</code>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>quarkus.funqy.knative-events.mapping.{function name}.trigger</code> sets the Cloud Event type that triggers a specific function</p>
</li>
<li>
<p><code>quarkus.funqy.knative-events.mapping.{function name}.response-type</code> sets the Cloud Event type of the response</p>
</li>
<li>
<p><code>quarkus.funqy.knative-events.mapping.{function name}.resource-source</code> sets the Cloud Event source of the response</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The Funqy Knative Events extension also has annotations to do this Cloud Event mapping to your functions.  Take a look at the
<code>annotatedChain</code> method</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.funqy.Funq;
import io.quarkus.funqy.knative.events.CloudEventMapping;

public class SimpleFunctionChain {
    @Funq
    @CloudEventMapping(trigger = "annotated", responseSource = "annotated", responseType = "lastChainLink")
    public String annotatedChain(String input) {
        log.info("*** annotatedChain ***");
        return input + "::" + "annotatedChain";
    }</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you use the <code>@CloudEventMapping</code> annotation on your function you can map the Cloud Event type trigger
and the Cloud Event response.  In this example the <code>annotatedChain</code> function will be triggered
by the <code>annotated</code> Cloud Event type and the response will be mapped to a <code>lastChainLink</code> type
and <code>annotated</code> Cloud Event source.</p>
</div>
<div class="paragraph">
<p>So, if look at all the functions defined within <code>SimpleFunctionChain</code> you&#8217;ll notice that one function triggers the next.
The last function that is triggered is <code>lastChainLink</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import io.quarkus.funqy.Context;
import io.quarkus.funqy.Funq;

public class SimpleFunctionChain {
    @Funq
    public void lastChainLink(String input, @Context CloudEvent event) {
        log.info("*** lastChainLink ***");
        log.info(input + "::" + "lastChainLink");
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>There are two things to notice about this function.  One, it has no output.  Your functions are not
required to return output.  Second, there is an additional <code>event</code> parameter to the function.</p>
</div>
<div class="paragraph">
<p>If you want to know additional information about the incoming Cloud Event, you can inject the
<code>CloudEvent</code> interface using the Funqy <code>@Context</code> annotation.  The <code>CloudEvent</code> interface exposes information
about the triggering event.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface CloudEvent {
    String id();
    String specVersion();
    String source();
    String subject();
    OffsetDateTime time();
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="maven"><a class="anchor" href="#maven"></a>Maven</h2>
<div class="sectionbody">
<div class="paragraph">
<p>If you look at the <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/pom.xml">pom</a>,
you&#8217;ll see that it is a typical Quarkus pom that pulls in one funqy dependency</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-funqy-knative-events&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="dev-mode-and-testing"><a class="anchor" href="#dev-mode-and-testing"></a>Dev mode and Testing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Funqy Knative Events support dev mode and unit testing using RestAssured.  You can invoke on Funqy Knative Events functions
using the same invocation model as
<a href="funqy-http">Funqy HTTP</a> using normal HTTP requests, or Cloud Event Binary mode, or Structured Mode.  All
invocation modes are supported at the same time.</p>
</div>
<div class="paragraph">
<p>So, if you open up the unit test code in <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/src/test/java/org/acme/funqy/FunqyTest.java">FunqyTest.java</a>
you&#8217;ll see that its simply using RestAssured to make HTTP invocations to test the functions.</p>
</div>
<div class="paragraph">
<p>Funqy also works with Quarkus Dev mode!</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="build-the-project"><a class="anchor" href="#build-the-project"></a>Build the Project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First build the Java artifacts:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn clean install</code></pre>
</div>
</div>
<div class="paragraph">
<p>Next, a docker image is required by Knative, so you&#8217;ll need to build that next:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker build -f src/main/docker/Dockerfile.jvm -t yourAccountName/funqy-knative-events-quickstart .</code></pre>
</div>
</div>
<div class="paragraph">
<p>Make sure to replace <code>yourAccountName</code> with your docker or quay account name when you run <code>docker build</code>.  The
Dockerfile is a standard Quarkus dockerfile.  No special Knative magic.</p>
</div>
<div class="paragraph">
<p>Push your image to docker hub or quay</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">docker push yourAccountName/funqy-knative-events-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>Again, make sure to replace <code>yourAccountName</code> with your docker or quay account name when you run <code>docker push</code>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="deploy-to-kubernetesopenshift"><a class="anchor" href="#deploy-to-kubernetesopenshift"></a>Deploy to Kubernetes/Openshift</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The first step is to define a Kubernetes/Openshift service to points to your the docker image you created and pushed
during build.  Take a look at <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/src/main/k8s/funqy-service.yaml">funqy-service.yaml</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: funqy-knative-events-quickstart
spec:
  template:
    metadata:
      name: funqy-knative-events-quickstart-v1
      annotations:
        autoscaling.knative.dev/target: "1"
    spec:
      containers:
        - image: docker.io/yourAccountName/funqy-knative-events-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>This is a standard Kubernetes service definition yaml file.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
Make sure you change the image url to point to the image you built and pushed earlier!
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>For our quickstart, one Kubernetes service will contain all functions.  There&#8217;s no reason you couldn&#8217;t break up this
quickstart into multiple different projects and deploy a service for each function.  For simplicity, and to show that you
don&#8217;t have to have a deployment per function, the quickstart combines everything into one project, image, and service.</p>
</div>
<div class="paragraph">
<p>Deploy the service yaml.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">kubectl apply -n knativetutorial -f src/main/k8s/funqy-service.yaml</code></pre>
</div>
</div>
<div class="paragraph">
<p>The next step is to deploy Knative Event triggers for each of the event types.  As noted in the code section, each
Funqy function is mapped to a specific Cloud Event type.  You must create Knative Event triggers that map a Cloud Event
and route it to a specific Kubernetes service.  We have 4 different triggers.</p>
</div>
<div class="paragraph">
<p><a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/funqy-quickstarts/funqy-knative-events-quickstart/src/main/k8s/defaultChain-trigger.yaml">defaultChain-trigger.yaml</a></p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="yaml" class="language-yaml hljs">apiVersion: eventing.knative.dev/v1alpha1
kind: Trigger
metadata:
  name: defaultchain
spec:
  filter:
    attributes:
      type: defaultChain
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: funqy-knative-events-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>spec:filter:attributes:type</code> maps a Cloud Event type to the Kubernetes service defined in <code>spec:subscriber:ref</code>.
When a Cloud Event is pushed to the Broker, it will trigger the spin up of the service mapped to that event.</p>
</div>
<div class="paragraph">
<p>There&#8217;s a trigger yaml file for each of our 4 Funqy functions.  Deploy them all:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">kubectl apply -n knativetutorial -f src/main/k8s/defaultChain-trigger.yaml
kubectl apply -n knativetutorial -f src/main/k8s/configChain-trigger.yaml
kubectl apply -n knativetutorial -f src/main/k8s/annoatedChain-trigger.yaml
kubectl apply -n knativetutorial -f src/main/k8s/lastChainLink-trigger.yaml</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run-the-demo"><a class="anchor" href="#run-the-demo"></a>Run the demo</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You&#8217;ll need two different terminal windows.  One to do a curl request to the Broker, the other to watch the pod log
files so you can see the messages flowing through the Funqy function event chain.</p>
</div>
<div class="paragraph">
<p>Make sure you have the <code>stern</code> tool installed.  See the Knative Tutorial setup for information on that.  Run stern
to look for logs outputed by our Funqy deployment</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">stern funq user-container</code></pre>
</div>
</div>
<div class="paragraph">
<p>Open a separate terminal.  You&#8217;ll first need to learn the URL of the broker.  Execute this command to find it.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">kubectl get broker default -o jsonpath='{.status.address.url}'</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will provide you a url like this (exactly like this if you followed the knative tutorial): <code><a href="http://default-broker.knativetutorial.svc.cluster.local" class="bare">http://default-broker.knativetutorial.svc.cluster.local</a></code>
Remember this URL.</p>
</div>
<div class="paragraph">
<p>Next thing we need to do is ssh into our Kubernetes cluster so that we can send a curl request to our broker.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">kubectl -n knativetutorial exec -it curler -- /bin/bash</code></pre>
</div>
</div>
<div class="paragraph">
<p>You will now be in a shell within the Kubernetes cluster.  Within the shell, execute this curl command</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">curl -v "http://default-broker.knativetutorial.svc.cluster.local" \
-X POST \
-H "Ce-Id: 1234" \
-H "Ce-Specversion: 1.0" \
-H "Ce-Type: defaultChain" \
-H "Ce-Source: curl" \
-H "Content-Type: application/json" \
-d '"Start"'</code></pre>
</div>
</div>
<div class="paragraph">
<p>This posts a Knative Event to the broker, which will trigger the <code>defaultChain</code> function.  As discussed earlier, the output
of <code>defaultChain</code> triggers an event that is posted to <code>configChain</code> which triggers an event posted to <code>annotatedChain</code> then
finally to the <code>lastChainLink</code> function.  You can see this flow in your <code>stern</code> window.  Something like this should
be outputted.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">funqy-knative-events-quickstart-v1-deployment-59bb88bcf4-9jwdx user-container 2020-05-12 13:44:02,256 INFO  [org.acm.fun.SimpleFunctionChain] (executor-thread-1) *** defaultChain ***
funqy-knative-events-quickstart-v1-deployment-59bb88bcf4-9jwdx user-container 2020-05-12 13:44:02,365 INFO  [org.acm.fun.SimpleFunctionChain] (executor-thread-2) *** configChain ***
funqy-knative-events-quickstart-v1-deployment-59bb88bcf4-9jwdx user-container 2020-05-12 13:44:02,394 INFO  [org.acm.fun.SimpleFunctionChain] (executor-thread-1) *** annotatedChain ***
funqy-knative-events-quickstart-v1-deployment-59bb88bcf4-9jwdx user-container 2020-05-12 13:44:02,466 INFO  [org.acm.fun.SimpleFunctionChain] (executor-thread-2) *** lastChainLink ***
funqy-knative-events-quickstart-v1-deployment-59bb88bcf4-9jwdx user-container 2020-05-12 13:44:02,467 INFO  [org.acm.fun.SimpleFunctionChain] (executor-thread-2) Start::defaultChain::configChain::annotatedChain::lastChainLink</code></pre>
</div>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
